home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / driverss.zip / UBNICPC.ASM < prev    next >
Assembly Source File  |  1991-02-11  |  16KB  |  694 lines

  1. version    equ    1
  2.  
  3. ;History:25,1 0
  4.  
  5. ; Copyright, 1990, Russell Nelson
  6.  
  7. ;   This program is free software; you can redistribute it and/or modify
  8. ;   it under the terms of the GNU General Public License as published by
  9. ;   the Free Software Foundation, version 1.
  10. ;
  11. ;   This program is distributed in the hope that it will be useful,
  12. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ;   GNU General Public License for more details.
  15. ;
  16. ;   You should have received a copy of the GNU General Public License
  17. ;   along with this program; if not, write to the Free Software
  18. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.  
  21.     include    defs.asm
  22.  
  23. ;some generic information about buffer lengths, etc
  24. XMITBUF_LEN    equ    800h        ;Transmit buffer length
  25. RPAGE_LEN    equ    128        ;receive page is 128 bytes
  26. NUM_RPAGES    equ    96        ;There are 96 receive pages
  27. NUM_XBUFS    equ    2        ;Number of xmit buffers
  28. NUM_XBUFS_MASK    equ    1
  29.  
  30. ub_seg    segment at 0
  31.  
  32.     org    10h
  33. eaddr_rom    db    6 dup(?)    ;Has serial # in 3 & 4th bytes
  34.  
  35.     org    2080h
  36. tsa_msb        db    ?    ;transmitter start address, high order 4
  37.                 ;bits on write, start send on read
  38. tsa_lsb        db    ?    ;Transmitter start address, least
  39.                 ;significant byte on write, clear PAV
  40.                 ;on read
  41.  
  42. ;Control / status register (CSR)
  43.  
  44. csr        db    ?    ;Control on write, status on read port
  45.  
  46. ;Command bits
  47. TxRdyIntEn    equ    080h        ;allow TxRdy interrupts
  48. PAVIntEn    equ    040h        ;Allow PAV to gen. intr.
  49. SFTInt        equ    020h        ;generate an interrupt reg.
  50. TimIntEn    equ    010h        ;allow Time interrupt req.
  51. ;status bits
  52. NTxRdyInt    equ    080h        ;Not req. TxRdy inter.
  53. NPAVInt        equ    040h        ;Not req. Pav intr.
  54. NSFTInt        equ    020h        ;Not req. SFTInt inter.
  55. NTimInt        equ    010h        ;Not req. timer inter.
  56. NRINT        equ    008h        ;Not req. recv inter.
  57. NTINT        equ    004h        ;Not req. xmit inter.
  58. TPOK        equ    002h        ;Packet okay of some type
  59. TXDONE        equ    001h        ;Transmit done
  60.  
  61. ;Page pointer register definitions
  62.  
  63. ffp        label    byte        ;ffp - first free page register
  64. epp        label    byte        ;epp - empty page pointer register
  65. pp        db    ?        ;ffp on write/epp on read
  66.  
  67.  
  68. ;ffp bits
  69. NIC_IE        equ    080h        ;NIC interrupts enable
  70.  
  71. ;epp bits
  72. PAV        equ    080h        ;Page available
  73. RPAGE_BITS    equ    07fh
  74.  
  75.  
  76.     org    2100h
  77. page_ram    db    NUM_RPAGES dup(?);Receiver buffer pages
  78.  
  79.     org    2180h
  80. tstatus        db    ?        ;Transmitter status 80
  81.  
  82. ;Transmit status bits - EDLC
  83. TX_READY    equ    080h        ;
  84. TX_BUSY        equ    040h        ;Carrier detect
  85. TX_TPR        equ    020h        ;Self received packet sent
  86. TX_SHORTED    equ    010h        ;Carrier lost
  87. TX_UF        equ    008h        ;Underflow
  88. TX_COL        equ    004h        ;Collision
  89. TX_C16        equ    002h        ;16 collisions
  90. TX_PE        equ    001h        ;Parity error
  91.  
  92. TXERRMASK    equ    TX_PE or TX_C16 or TX_COL or TX_UF or TX_SHORTED or TX_BUSY
  93.  
  94. tmask        db    ?        ;Transmitter mask 81
  95. rstatus        db    ?        ;Receiver status
  96. rmask        db    ?        ;Receiver mask 83
  97. tmode        db    ?        ;Transmitter mode 84
  98. rmode        db    ?        ;Receiver mode 85
  99. reset        db    ?        ;Reset line - high on bit 7, 86
  100. tdrlsb        db    ?        ;TDR lsb  87
  101. eaddr_ram    db    6 dup(?)    ;current Ethernet address.
  102.         db    ?        ;Reserved 8e
  103. tdrmsb        db    ?        ;TDR msb 8f
  104.  
  105.     org    4000h
  106. receive_buf    label    byte
  107.  
  108.     org    7000h
  109. transmit_buf_1    label    byte
  110.  
  111.     org    7800h
  112. transmit_buf_2    label    byte
  113.  
  114. ub_seg    ends
  115.  
  116. code    segment    word public
  117.     assume    cs:code, ds:code
  118.  
  119.     public    int_no
  120. int_no        db    3,0,0,0        ;must be four bytes long for get_number.
  121. base_addr    dw    0d000h,0
  122.  
  123.     public    driver_class, driver_type, driver_name, driver_function, parameter_list
  124. driver_class    db    BLUEBOOK, IEEE8023, 0        ;from the packet spec
  125. driver_type    db    8        ;from the packet spec
  126. driver_name    db    'PC-NIC',0    ;name of the driver.
  127. driver_function    db    2
  128. parameter_list    label    byte
  129.     db    1    ;major rev of packet driver
  130.     db    9    ;minor rev of packet driver
  131.     db    14    ;length of parameter list
  132.     db    EADDR_LEN    ;length of MAC-layer address
  133.     dw    GIANT    ;MTU, including MAC headers
  134.     dw    MAX_MULTICAST * EADDR_LEN    ;buffer size of multicast addrs
  135.     dw    0    ;(# of back-to-back MTU rcvs) - 1
  136.     dw    0    ;(# of successive xmits) - 1
  137. int_num    dw    0    ;Interrupt # to hook for post-EOI
  138.             ;processing, 0 == none,
  139.  
  140.     public    rcv_modes
  141. rcv_modes    dw    7        ;number of receive modes in our table.
  142.         dw    0               ;There is no mode zero
  143.         dw    rcv_mode_1
  144.         dw    0        ;don't want to bother.
  145.         dw    rcv_mode_3
  146.         dw    0        ;haven't set up perfect filtering yet.
  147.         dw    rcv_mode_5
  148.         dw    rcv_mode_6
  149.  
  150. current_page    db    0        ;current receiver page
  151.  
  152. active_buffer    dw    transmit_buf_1
  153. inactive_buffer    dw    transmit_buf_2
  154.  
  155.     include    movemem.asm
  156.  
  157.     public    as_send_pkt
  158. ; The Asynchronous Transmit Packet routine.
  159. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  160. ;   interrupts possibly enabled.
  161. ; Exit with nc if ok, or else cy if error, dh set to error number.
  162. ;   es:di and interrupt enable flag preserved on exit.
  163. as_send_pkt:
  164.     ret
  165.  
  166.     public    drop_pkt
  167. ; Drop a packet from the queue.
  168. ; Enter with es:di -> iocb.
  169. drop_pkt:
  170.     assume    ds:nothing
  171.     ret
  172.  
  173.     public    xmit
  174. ; Process a transmit interrupt with the least possible latency to achieve
  175. ;   back-to-back packet transmissions.
  176. ; May only use ax and dx.
  177. xmit:
  178.     assume    ds:nothing
  179.     ret
  180.  
  181.  
  182.     public    send_pkt
  183. send_pkt:
  184. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  185. ;  (only if the high-performance bit is set in driver_function)
  186. ;enter with ds:si -> packet, cx = packet length.
  187. ;if we're a high-performance driver, es:di -> upcall.
  188. ;exit with nc if ok, or else cy if error, dh set to error number.
  189.     assume    ds:nothing
  190.  
  191.     mov    es,base_addr
  192.     assume    es:ub_seg
  193.  
  194.     cmp    cx,GIANT        ; Is this packet too large?
  195.     ja    send_pkt_toobig
  196.  
  197.     cmp    cx,RUNT            ; minimum length for Ether
  198.     jnb    oklen
  199.     mov    cx,RUNT            ; make sure size at least RUNT
  200. oklen:
  201.  
  202.     mov    di,XMITBUF_LEN        ;compute where we're going to
  203.     sub    di,cx            ;  be putting the packet.
  204.  
  205. ;games above ensure that the last byte of data to go out is at the
  206. ;end of the ub xmit buffer, pos is really the offset from the
  207. ;start of that buffer
  208.  
  209.     mov    ax,active_buffer    ;swap the buffer pointers.
  210.     xchg    ax,inactive_buffer
  211.     mov    active_buffer,ax
  212.     add    di,ax
  213.     push    di
  214.     call    movemem
  215.     pop    di
  216.  
  217. ;Wait for previous packet to finish first
  218. ;could do this with interrupts, etc, but with only 2 xmit buffers
  219. ;doesn't seem worth the effort
  220.  
  221. send_pkt_1:
  222.     mov    al,csr
  223.     and    al,TPOK or TXDONE
  224.     cmp    al,TPOK or TXDONE
  225.     jne    send_pkt_1
  226.  
  227.     mov    al,tstatus        ;get xmiter status ...
  228.     mov    tstatus,0fh        ;... and clear status bits
  229.  
  230.     test    al,TXERRMASK        ;any errors?
  231.     je    send_pkt_2
  232.     call    count_out_err        ;yes, count them.
  233. send_pkt_2:
  234.  
  235. ;all done above, we can play with TSA now!
  236. ;give offset
  237.  
  238.     mov    ax,di
  239.     mov    tsa_lsb,al
  240.     mov    tsa_msb,ah
  241.  
  242.     cmp    al,tsa_msb        ;Start the send in action (SIDEEFFECT)
  243.  
  244.     clc
  245.     ret
  246. send_pkt_toobig:
  247.     mov    dh,NO_SPACE
  248.     stc
  249.     ret
  250.  
  251.     public    get_address
  252. get_address:
  253. ;get the address of the interface.
  254. ;enter with es:di -> place to get the address, cx = size of address buffer.
  255. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  256.     assume    ds:code
  257.     cmp    cx,EADDR_LEN        ;make sure that we have enough room.
  258.     jb    get_address_2
  259.  
  260.     push    ds
  261.     mov    ds,base_addr
  262.     mov    si,offset eaddr_rom
  263.     mov    cx,EADDR_LEN
  264.     rep    movsb
  265.     pop    ds
  266.  
  267.     mov    cx,EADDR_LEN
  268.     clc
  269.     ret
  270. get_address_2:
  271.     stc
  272.     ret
  273.  
  274.  
  275.     public    set_address
  276. set_address:
  277. ;enter with ds:si -> Ethernet address, CX = length of address.
  278. ;exit with nc if okay, or cy, dh=error if any errors.
  279.     assume    ds:nothing
  280.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  281.     je    set_address_4
  282.     mov    dh,BAD_ADDRESS
  283.     stc
  284.     jmp    short set_address_done
  285. set_address_4:
  286.  
  287.     mov    es,base_addr
  288.     mov    di,offset eaddr_ram
  289.     rep    movsb
  290. ;    call    initialize        ;initialize with our new address.
  291.  
  292. set_address_okay:
  293.     mov    cx,EADDR_LEN        ;return their address length.
  294.     clc
  295. set_address_done:
  296.     push    cs
  297.     pop    ds
  298.     assume    ds:code
  299.     ret
  300.  
  301.  
  302. ;    0 - accept no packets
  303. rcv_mode_1:
  304.     mov    es,base_addr
  305.     assume    es:ub_seg
  306.  
  307.     mov    rmode,0
  308.     ret
  309.  
  310. rcv_mode_3:
  311. ;    1 - accept node id packets, multicasts which match first three
  312. ;        bytes of node id, and broadcasts
  313.     mov    es,base_addr
  314.     assume    es:ub_seg
  315.  
  316.     mov    rmode,1
  317.     ret
  318.  
  319. ;    2 - accept node id packets, all multicasts and broadcasts
  320. rcv_mode_5:
  321.     mov    es,base_addr
  322.     assume    es:ub_seg
  323.  
  324.     mov    rmode,2
  325.     ret
  326.  
  327. ;    3 - take all, promiscous
  328. rcv_mode_6:
  329.     mov    es,base_addr
  330.     assume    es:ub_seg
  331.  
  332.     mov    rmode,3
  333.     ret
  334.  
  335.     public    set_multicast_list
  336. set_multicast_list:
  337. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  338. ;return nc if we set all of them, or cy,dh=error if we didn't.
  339.     mov    dh,NO_MULTICAST
  340.     stc
  341.     ret
  342.  
  343.  
  344.     public    terminate
  345. terminate:
  346.     mov    es,base_addr
  347.     assume    es:ub_seg
  348.  
  349.     mov    ffp,0            ;set ffp to zero - disabling PAV
  350.     mov    csr,0            ;Turn off interrupt masks here and ...
  351.     mov    tmask,0            ;reset edlc interrupt masks
  352.     mov    rmask,0
  353.     mov    reset,80h        ;Turn on reset line
  354.  
  355.     ret
  356.  
  357.     public    reset_interface
  358. reset_interface:
  359. ;reset the interface.
  360.     assume    ds:code
  361.     ret
  362.  
  363.  
  364. ;called when we want to determine what to do with a received packet.
  365. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  366.     extrn    recv_find: near
  367.  
  368. ;called after we have copied the packet into the buffer.
  369. ;enter with ds:si ->the packet, cx = length of the packet.
  370.     extrn    recv_copy: near
  371.  
  372.     extrn    count_in_err: near
  373.     extrn    count_out_err: near
  374.  
  375.  
  376.     public    recv
  377. recv:
  378. ;called from the recv isr.  All registers have been saved, and ds=cs.
  379. ;Upon exit, the interrupt will be acknowledged.
  380.     assume    ds:code
  381.  
  382.     mov    es,base_addr
  383.     assume    es:ub_seg
  384.  
  385. recv_3:
  386.     test    epp,PAV
  387.     jne    recv_4
  388.     jmp    recv_2            ;yes.
  389. recv_4:
  390.  
  391. ;checking against epp is a pain actually...
  392.     xor    cx,cx            ;start with zero length
  393.     mov    bl,current_page        ;get the first page.
  394.     xor    bh,bh
  395.     mov    dx,bx            ;remember the first page.
  396. count_pages_1:
  397.     mov    al,page_ram[bx]        ;Get page descriptor
  398.     and    al,RPAGE_BITS        ;Only page offset bits PLEASE
  399.     inc    al            ;Add 1 to offset to make length
  400.     xor    ah,ah
  401.     add    cx,ax            ;Add in current page length
  402.  
  403.     mov    al,page_ram[bx]        ;Get page descriptor
  404.     inc    bx            ;go to the next page
  405.     cmp    bx,NUM_RPAGES        ;wrap around if necessary.
  406.     jb    count_pages_2
  407.     xor    bx,bx
  408. count_pages_2:
  409.  
  410.     test    al,80h            ;End page?
  411.     je    count_pages_1        ;yes, go add this one's length.
  412.  
  413.     mov    current_page,bl
  414.  
  415.     mov    ax,dx            ;multiply dx by RPAGE_LEN.
  416.     xchg    ah,al
  417.     ror    ax,1
  418.     mov    di,ax
  419.     add    di,offset receive_buf    ;get the starting address.
  420.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  421.                     ;  point to the packet type.
  422.     push    bx
  423.     push    cx
  424.     push    dx
  425.  
  426.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  427.     mov    ax, es:[di]
  428.     xchg    ah, al
  429.     cmp     ax, 1500
  430.     ja    BlueBookPacket
  431.     inc    di            ;set di to 802.2 header
  432.     inc    di
  433.     mov    dl, IEEE8023
  434. BlueBookPacket:
  435.  
  436.     call    recv_find        ;look up our type.
  437.     assume    es:nothing
  438.     pop    dx
  439.     pop    cx
  440.     pop    bx
  441.  
  442.     mov    ax,es            ;is this pointer null?
  443.     or    ax,di
  444.     je    just_discard        ;yes - just free the frame.
  445.  
  446.     push    cx
  447.     push    di
  448.     push    es
  449.  
  450.     cmp    dx,bx            ;did we wrap around (first >last?)
  451.     jbe    no_wrap            ;no, just do one move.
  452.  
  453. ;we wrapped around the buffer, so we have to move in two halves.
  454. ;move the first part.
  455.     mov    ax,dx            ;multiply dx by RPAGE_LEN.
  456.     xchg    ah,al
  457.     ror    ax,1
  458.     mov    si,ax
  459.     add    si,offset receive_buf    ;get the starting address.
  460.  
  461.     mov    ax,NUM_RPAGES        ;Compute the number of pages to move.
  462.     sub    ax,dx
  463.     xchg    ah,al            ;convert to pages (*RPAGE_LEN).
  464.     ror    ax,1
  465.     cmp    cx,ax            ;are we moving less than that?
  466.     jbe    no_wrap            ;yes, just move it.
  467.     sub    cx,ax            ;reduce the total count by this count.
  468.     push    cx            ;preserve the second part's count
  469.     mov    cx,ax            ;get the first part's count.
  470.  
  471.     push    ds
  472.     mov    ds,base_addr
  473.     assume    ds:nothing
  474.     call    movemem
  475.     assume    ds:code
  476.     pop    ds
  477.  
  478.     pop    cx            ;get back the count
  479.  
  480.     xor    dx,dx
  481.  
  482. no_wrap:
  483.     mov    ax,dx            ;multiply dx by 128.
  484.     xchg    ah,al
  485.     ror    ax,1
  486.     mov    si,ax
  487.     add    si,offset receive_buf
  488.     mov    ds,base_addr
  489.     assume    ds:nothing
  490.     call    movemem
  491.     assume    ds:code
  492.  
  493.     pop    ds
  494.     pop    si
  495.     pop    cx
  496.     call    recv_copy
  497.     push    cs
  498.     pop    ds
  499.  
  500. just_discard:
  501.     mov    es,base_addr
  502.     assume    es:ub_seg
  503.     mov    al,epp            ;Any more packets left?
  504.     and    al,RPAGE_BITS
  505.     cmp    al,current_page
  506.     je    recv_5
  507.     jmp    recv_3
  508. recv_5:
  509.  
  510.     cmp    al,tsa_lsb        ;Clearing pav bit (SIDEEFFECT)
  511.  
  512. recv_2:
  513.  
  514. ;Ack the interrupt by turning bit on and off
  515.     mov    al,current_page        ;Set first free page pointer
  516.     mov    ffp,al
  517.     or    al,NIC_IE        ;set interrupt bit, was off
  518.     mov    ffp,al
  519. recv_1:
  520.     ret
  521.  
  522.  
  523.     public    recv_exiting
  524. recv_exiting:
  525. ;called from the recv isr after interrupts have been acknowledged.
  526. ;Only ds and ax have been saved.
  527.     assume    ds:nothing
  528.     ret
  529.  
  530.  
  531. ;any code after this will not be kept after initialization.
  532. end_resident    label    byte
  533.  
  534.  
  535.     public    usage_msg
  536. usage_msg    db    "usage: ubnic [-n] [-d] [-w] <packet_int_no> <int_no> <base_addr>",CR,LF,'$'
  537.  
  538.     public    copyright_msg
  539. copyright_msg    db    "Packet driver for the UB PC/NIC, version ",'0'+majver,".",'0'+version,CR,LF
  540.         db    '$'
  541.  
  542. int_no_name    db    "Interrupt number ",'$'
  543. base_addr_name    db    "Memory address ",'$'
  544. our_address    db    6 dup(?)    ;temporarily hold our address
  545.  
  546.     extrn    set_recv_isr: near
  547.  
  548. ;enter with si -> argument string, di -> wword to store.
  549. ;if there is no number, don't change the number.
  550.     extrn    get_number: near
  551.  
  552. ;enter with si -> argument string, di -> wword to print.
  553.     extrn    print_number: near
  554.  
  555.     public    parse_args
  556. parse_args:
  557. ;exit with nc if all went well, cy otherwise.
  558.     mov    di,offset int_no
  559.     call    get_number
  560.     mov    di,offset base_addr
  561.     call    get_number
  562.     clc
  563.     ret
  564.  
  565.  
  566.     public    etopen
  567. etopen:
  568.     cli
  569.  
  570.     cmp    base_addr,-1        ;did they ask for auto-configure?
  571.     jne    no_auto_config
  572.  
  573.     mov    bx,8000h        ;yes, they *could* address it there.
  574. auto_config_1:
  575.     mov    es,bx
  576.     assume    es:ub_seg
  577.     cmp    word ptr es:eaddr_rom[0],00h + 0ddh * 256
  578.     jne    auto_config_2
  579.     cmp    byte ptr es:eaddr_rom[2],01h
  580.     je    auto_config_3
  581. auto_config_2:
  582.     add    bx,800h            ;move up by 32K
  583.     jnc    auto_config_1        ;go if we didn't overflow.
  584.     sti
  585.     stc                ;say that we couldn't init.
  586.     ret
  587.  
  588. auto_config_3:
  589.     mov    base_addr,bx        ;remember where we found it.
  590.     mov    base_addr+2,0        ;and nuke the rest of the -1.
  591.  
  592. no_auto_config:
  593.     mov    es,base_addr
  594.     assume    es:ub_seg
  595.  
  596.     mov    reset,80h        ;Turn on reset line to tie down NIC
  597.     mov    rmode,0            ;no packets for now
  598.     mov    tmode,0            ;Turn on loopback
  599.  
  600.     mov    al,epp            ;start ffp at epp - eliminates bogus ....
  601.     and    al,07fh
  602.     mov    current_page,al        ;... packets if we've been started before
  603.     mov    ffp,al            ;Make sure interrupt enable is dead
  604.  
  605.     cmp    al,tsa_lsb        ;Clearing pav bit (SIDEEFFECT)
  606.  
  607.     mov    tstatus, 0fh        ;Clear xmit status bits
  608.     mov    tmask,0            ;No xmit intrs
  609.     mov    rmask,0            ;'Packet okay' only?
  610.     mov    rstatus,0ffh        ;Clear receiver status bits
  611.  
  612.     push    ds
  613.     pop    es
  614.     mov    di,offset our_address
  615.     mov    cx,EADDR_LEN
  616.     call    get_address
  617.     mov    si,offset our_address
  618.     mov    cx,EADDR_LEN
  619.     call    set_address
  620.  
  621. ;Since first packet will get sent no matter what we do, let's make it
  622. ;something everyone (include me) will ignore
  623. ;set length to zero
  624.  
  625.     mov    tsa_lsb,0ffh        ;Get last 8 bits
  626.     mov    tsa_msb,0fh        ;and top 4 bits
  627.  
  628.     mov    reset,0            ;Clear reset - expect packet to go
  629. ;Wait for packet to go!
  630. etopen_1:
  631.     mov    al,csr
  632.     and    al,TPOK or TXDONE
  633.     cmp    al,TPOK or TXDONE
  634.     jne    etopen_1
  635.  
  636.     mov    tstatus,0fh        ;clear xmiter status
  637.     mov    tmode,0ah        ;Clear loopbk, set parity enable
  638.  
  639.     mov    csr,0            ;make sure this interrupt was off first
  640.     mov    csr,PAVIntEn        ;Page frame available interrupt only
  641.     mov    al,current_page        ;Set first free page register ...
  642.     or    al,NIC_IE
  643.     mov    ffp,al            ;... and make sure interrupts enabled
  644.  
  645.     mov    al,epp            ;get epp again
  646.     test    al,PAV
  647.     je    etopen_2
  648.     cmp    al,tsa_lsb        ;Try clearing pav bit (SIDEEFFECT)
  649. etopen_2:
  650.  
  651. ;enable receiving now
  652. ;    1 - accept node id packets, multicasts which match first three
  653. ;        bytes of node id, and broadcasts
  654.     mov    rmode,1
  655.  
  656. ;
  657. ; Now hook in our interrupt
  658. ;
  659.     call    set_recv_isr
  660.  
  661.     sti
  662.  
  663.     mov    al, int_no        ; Get board's interrupt vector
  664.     add    al, 8
  665.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  666.     jb    set_int_num        ; No.
  667.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  668. set_int_num:
  669.     xor    ah, ah            ; Clear high byte
  670.     mov    int_num, ax        ; Set parameter_list int num.
  671.  
  672. ;if all is okay,
  673.     mov    dx,offset end_resident
  674.     clc
  675.     ret
  676. ;if we got an error,
  677.     stc
  678.     ret
  679.  
  680.     public    print_parameters
  681. print_parameters:
  682. ;echo our command-line parameters
  683.     mov    di,offset int_no
  684.     mov    dx,offset int_no_name
  685.     call    print_number
  686.     mov    di,offset base_addr
  687.     mov    dx,offset base_addr_name
  688.     call    print_number
  689.     ret
  690.  
  691. code    ends
  692.  
  693.     end
  694.